package com.tuanzi.loan.core.aspect;

import java.util.Arrays;
import java.util.stream.Collectors;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Aspect
@Component
public class DebugAspect implements ApplicationContextAware {

	private ApplicationContext applicationContext;
	private boolean debug;

	@PostConstruct
	private void init() {
		String systemDebugProperty = applicationContext.getEnvironment().getProperty("system.debug");
		if (!StringUtils.isBlank(systemDebugProperty)) {
			debug = Boolean.valueOf(systemDebugProperty);
		}
	}

	@Around("(execution(* ((@Debug *)+).*(..)) && within(@Debug *) || execution(@Debug * *(..))) && this(target)")
	public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint, final Object target) throws Throwable {
		if (!debug) {
			return proceedingJoinPoint.proceed();
		}

		Long startAt = System.currentTimeMillis();
		String args = Arrays.asList(proceedingJoinPoint.getArgs()).stream().map(x -> x == null ? "null" : x.toString()).collect(Collectors.joining(","));
		Object result = proceedingJoinPoint.proceed();
		Long spentTime = System.currentTimeMillis() - startAt;
		String resultStr = result == null ? "void" : result.toString();

		log.info("invoking method : {} | args : {} | result : {} | time : {} milliseconds", proceedingJoinPoint.getSignature().toLongString(), args, resultStr, spentTime);
		return result;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}
}
